package br.ufrgs.tst.ga;

import java.security.InvalidParameterException;
import java.util.List;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;

import br.ufrgs.ga.fitness.TspTourFitnessCalculator;
import br.ufrgs.tsp.model.ICity;
import br.ufrgs.tst.TestHelper;

public class TestTourFitnessCalculator {

	private TspTourFitnessCalculator tourFitnessCalculator;
	private String dnaStrandWithValidTSPTour = "024130";
	private String dnaStrandWithInvalidTour = "012340";
	private String dnaStrandWithValidTourButInvalidTSPTour = "031314";
	private String dnaStrandWithValidTourButInvalidTSPTourCity4IsNotVisited = "0123567890";
	
	@Before
	public void setUp() {
		// Initial cities configuration for a TSP instance.
		List<ICity> citiesConfiguration = TestHelper.getCitiesConfigurationStub();
		this.tourFitnessCalculator = new TspTourFitnessCalculator(citiesConfiguration);
	}
	
	@Test
	public void calculateTest() {
		// A fitness with value equals to chromosome.getDnaStrand().length() (number of cities) is a valid TSP tour...
		Assert.assertEquals(0, tourFitnessCalculator.calculate(dnaStrandWithValidTSPTour).intValue());
		Assert.assertEquals(-3, tourFitnessCalculator.calculate(dnaStrandWithInvalidTour).intValue());
		Assert.assertEquals(-4, tourFitnessCalculator.calculate(dnaStrandWithValidTourButInvalidTSPTour).intValue());
		
		int fitness = Integer.MIN_VALUE;
		try {
			fitness = tourFitnessCalculator.calculate(dnaStrandWithValidTourButInvalidTSPTourCity4IsNotVisited).intValue();
			Assert.assertEquals(-1, fitness);
		} catch (InvalidParameterException e) {
			Assert.assertEquals(Integer.MIN_VALUE, fitness);
		}
	}
	
	@Test
	public void calculateFitnessValueForValidTourTest() {
		Assert.assertEquals(0, tourFitnessCalculator.calculateFitnessValueForValidTour(dnaStrandWithValidTSPTour));
		Assert.assertEquals(-3, tourFitnessCalculator.calculateFitnessValueForValidTour(dnaStrandWithInvalidTour));
		Assert.assertEquals(0, tourFitnessCalculator.calculateFitnessValueForValidTour(dnaStrandWithValidTourButInvalidTSPTour));
		
		int fitness = Integer.MIN_VALUE;
		try {
			fitness = tourFitnessCalculator.calculateFitnessValueForValidTour(dnaStrandWithValidTourButInvalidTSPTourCity4IsNotVisited);
			Assert.assertEquals(-1, fitness);
		} catch (InvalidParameterException e) {
			Assert.assertEquals(Integer.MIN_VALUE, fitness);
		}
	}
	
	@Test
	public void calculateFitnessValueForTSPTourTest() {
		int[] citiesVisitCount = tourFitnessCalculator.calculateCitiesVisitsCount(dnaStrandWithValidTSPTour);
		Assert.assertEquals(0, tourFitnessCalculator.calculateFitnessValueForTSPTour(dnaStrandWithValidTSPTour, citiesVisitCount));
		citiesVisitCount = tourFitnessCalculator.calculateCitiesVisitsCount(dnaStrandWithInvalidTour);
		Assert.assertEquals(0, tourFitnessCalculator.calculateFitnessValueForTSPTour(dnaStrandWithInvalidTour, citiesVisitCount));
		
		int fitness = Integer.MIN_VALUE;
		try {
			fitness = tourFitnessCalculator.calculateFitnessValueForValidTour(dnaStrandWithValidTourButInvalidTSPTourCity4IsNotVisited);
			Assert.assertEquals(-1, fitness);
		} catch (InvalidParameterException e) {
			Assert.assertEquals(Integer.MIN_VALUE, fitness);
		}
	}
}
